package com.system.queue.service.impl;
import com.alibaba.cloud.commons.lang.StringUtils;
import com.system.queue.bean.PageBean;
import com.system.queue.bean.ResultBean;
import com.system.queue.bean.TableBean;
import com.system.queue.domain.*;
import com.system.queue.dto.OrdinaryUserDTO;
import com.system.queue.dto.SpecialUserDTO;
import com.system.queue.dto.VisitQueueDTO;
import com.system.queue.feign.AppointmentServiceFeign;
import com.system.queue.feign.ConsultationRoomServiceFeign;
import com.system.queue.feign.EmployeeServiceFeign;
import com.system.queue.feign.PatientServiceFeign;
import com.system.queue.query.QueueQuery;
import com.system.queue.repository.QueueRepository;
import com.system.queue.service.QueueService;
import com.system.queue.strategy.OrdinaryStrategy;
import com.system.queue.strategy.SpecialStrategy;
import com.system.queue.utils.BirthToAgeUtil;
import com.system.queue.vo.QueueVO;
import jakarta.persistence.criteria.Predicate;
import org.modelmapper.ModelMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * @className: QueueServiceImpl
 * @description: TODO 类描述
 * @author: Kuangkeli
 * @date: 2023/11/27 19:03
 **/

@Service
public class QueueServiceImpl implements QueueService {

    @Autowired
    private QueueRepository queueRepository;

    @Autowired
    private PatientServiceFeign patientServiceFeign;

    @Autowired
    private AppointmentServiceFeign appointmentServiceFeign;

    @Autowired
    private ConsultationRoomServiceFeign consultationRoomServiceFeign;

    @Autowired
    private EmployeeServiceFeign employeeServiceFeign;

    private ModelMapper modelMapper = new ModelMapper();

    @Override
    public boolean saveQueue(Queue queue) {
        Queue obj = queueRepository.save(queue);
        if (obj != null) {
            return true;
        }
        return false;
    }

    @Override
    public boolean removeQueueById(int id) {
        if (queueRepository.existsById(id)) {
            queueRepository.deleteById(id);
            return true;
        }
        return false;
    }

    @Override
    public boolean modifyQueue(Queue queue) {
        Queue obj = queueRepository.save(queue);
        if (obj != null) {
            return true;
        }
        return false;
    }

    @Override
    public QueueVO getQueueById(int id) {
        //获取数据库中的队列持久层对象
        Queue queuePO = queueRepository.getReferenceById(id);
        //将持久层数据注入对象
        VisitQueueDTO visitQueueDTO = modelMapper.map(queuePO, VisitQueueDTO.class);
        Employee employee = employeeServiceFeign.getHandle(queuePO.getEmployeeId());
        visitQueueDTO.setEmployee(employee);
        Appointment appointment = appointmentServiceFeign.getAppointmentById(queuePO.getAppointmentId());
        visitQueueDTO.setAppointment(appointment);
        Patient patient = patientServiceFeign.getPatientById(appointment.getPatientId());
        visitQueueDTO.setPatient(patient);
        ConsultationRoom consultationRoom = consultationRoomServiceFeign.getHandle(queuePO.getConsultationId());
        visitQueueDTO.setConsultationRoom(consultationRoom);
        //将需要展示的数据注入视图对象
        QueueVO queueVO = modelMapper.map(visitQueueDTO, QueueVO.class);
        queueVO.setConsultationRoom(visitQueueDTO.getConsultationRoom().getCrName());
        queueVO.setPatientName(visitQueueDTO.getPatient().getPName());
        queueVO.setPatientAge(BirthToAgeUtil.calculateAge(visitQueueDTO.getPatient().getPBirth()));
        queueVO.setEmployeeName(visitQueueDTO.getEmployee().getEName());

        return queueVO;
    }


    @Override
    public PageBean<QueueVO> selectPage(QueueQuery query) {
        Pageable pageable = query.toPageable();
        Specification<Queue> spec = (root, criteriaQuery, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            if (query.getEmployeeID() != null) {
                predicates.add(criteriaBuilder.equal(root.get("employeeId"), query.getEmployeeID()));
            }
            if (query.getConsulationRoomID() != null) {
                predicates.add(criteriaBuilder.equal(root.get("consultationId"), query.getConsulationRoomID()));
            }
            return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
        };
        Page<Queue> page = queueRepository.findAll(spec, pageable);
        List<VisitQueueDTO> visitQueueDTOList = new ArrayList<>();
        List<QueueVO> queueVOList = new ArrayList<>();
        for (Queue queuePO : page.getContent()) {
            VisitQueueDTO visitQueueDTO = modelMapper.map(queuePO, VisitQueueDTO.class);
            Employee employee = employeeServiceFeign.getHandle(queuePO.getEmployeeId());
            visitQueueDTO.setEmployee(employee);
            Appointment appointment = appointmentServiceFeign.getAppointmentById(queuePO.getAppointmentId());
            visitQueueDTO.setAppointment(appointment);
            Patient patient = patientServiceFeign.getPatientById(appointment.getPatientId());
            visitQueueDTO.setPatient(patient);
            ConsultationRoom consultationRoom = consultationRoomServiceFeign.getHandle(queuePO.getConsultationId());
            visitQueueDTO.setConsultationRoom(consultationRoom);
            visitQueueDTOList.add(visitQueueDTO);
            QueueVO queueVO = modelMapper.map(visitQueueDTO, QueueVO.class);
            queueVO.setConsultationRoom(visitQueueDTO.getConsultationRoom().getCrName());
            queueVO.setPatientName(visitQueueDTO.getPatient().getPName());
            queueVO.setPatientAge(BirthToAgeUtil.calculateAge(visitQueueDTO.getPatient().getPBirth()));
            queueVO.setEmployeeName(visitQueueDTO.getEmployee().getEName());
            queueVO.setPriority(visitQueueDTO.getPriority());
            queueVOList.add(queueVO);
        }
        PageBean<QueueVO> queueVOPageBean = new PageBean<>();
        queueVOPageBean.setPageSize(page.getSize());
        queueVOPageBean.setPageNum(page.getNumber());
        queueVOPageBean.setTotal(page.getTotalElements());
        queueVOPageBean.setPages(page.getTotalPages());
        queueVOPageBean.setResult(queueVOList);
        return queueVOPageBean;
    }

    /**
     * 叫号功能实现 根据传来的医生id 采取策略 呼叫优先级最高的患者  将其状态改为请前往诊室就诊 如果多次呼叫次数
     * 超过策略规定的呼叫次数 则直接移除队列 设置出队时间  并顺延呼叫下一位患者
     * @param id
     * @return
     */
    @Override
    public Patient calling(Integer id) {
        QueueQuery query = new QueueQuery();
        query.setEmployeeID(id);
        Specification<Queue> spec = (root, criteriaQuery, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            if (query.getEmployeeID() != null) {
                predicates.add(criteriaBuilder.equal(root.get("employeeId"), query.getEmployeeID()));
            }
            return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
        };
        List<Queue> queueList = queueRepository.findAll(spec);
        Queue frist = queueList.get(0);
        frist.setState(2);
        frist.setDequeuetm(LocalDateTime.now());
        modifyQueue(frist);
        Appointment appointment = appointmentServiceFeign.getAppointmentById(frist.getAppointmentId());
        return patientServiceFeign.getPatientById(appointment.getPatientId());
    }
}
